﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections;

namespace GuanLongHooker
{
    class WindowOperation
    {

        #region
        //导入各种dll
        [DllImport("USER32.DLL")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        [DllImport("user32.dll", EntryPoint = "SendMessageA")]
        private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, string lParam);

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);

        //highlight function
        [DllImport("user32.dll")]
        static extern bool IsWindow(IntPtr hWnd);
        [DllImport("user32.dll")]
        static extern bool GetWindowRect(IntPtr hWnd, out Rectangle lpRect);
        [DllImport("user32.dll")]
        static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("gdi32.dll")]
        static extern bool PatBlt(IntPtr hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, uint dwRop);
        [DllImport("user32.dll")]
        static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
        static uint DSTINVERT = 0x00550009;

        //GetWindow
        [DllImport("User32.Dll")]
        public static extern IntPtr GetWindow(IntPtr hwnd, int wFlag);

        //GetWindowText
        [DllImport("user32.dll", EntryPoint = "GetWindowTextA", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);
        #endregion

        //-----------------------------------------------------------------------------------------------------------------------
        public IntPtr REPORTVALUEHANDLE = IntPtr.Zero;
        private static object myOpenJianCangDanOrPingCangDanWindowLock = new object();//打开建仓单窗口或平平仓单窗口线程锁

        private static WindowOperation instance = null;

        private WindowOperation()
        {
            
        }

        public static WindowOperation getInstance()
        {
            if (instance == null)
            {
                instance = new WindowOperation();
            }

            return instance;
        }

        //----------------------------------------------------------------------
        //找冠龙贵金属交易软件(客户版)2.6主界面句柄
        private IntPtr findMainWindow()
        {
            IntPtr hwnd = FindWindow(null, "冠龙贵金属交易软件(客户版)2.6");

            if (hwnd != IntPtr.Zero)
            {
                //Log.WriteLogFile("找到窗口: 冠龙贵金属交易软件(客户版)2.6");
            }
            else
            {
                Log.WriteLogFile("没有找到窗口: 冠龙贵金属交易软件(客户版)2.6");
            }
            return hwnd;
        }

        //打开建仓单(主界面存在, 点击建仓单按钮)
        //默认商品为白银1000
        public void openJianCangDanWindow()
        {
            lock (myOpenJianCangDanOrPingCangDanWindowLock)
            {
                closePingCangDanWindow();

                try
                {
                    if (findJianCangDanWindow() == IntPtr.Zero)//建仓单窗口未打开
                    {
                        IntPtr hwnd = findMainWindow();

                        if (hwnd != IntPtr.Zero)
                        {
                            FindWindow fw = new FindWindow(hwnd, null, "toolStrip1");

                            PostMessage(fw.FoundHandle, Win32.WM_LBUTTONDOWN, 0, Win32.MakeLong(22, 22));
                            PostMessage(fw.FoundHandle, Win32.WM_LBUTTONUP, 0, Win32.MakeLong(22, 22));
                            //PostMessage 是异步消息, 发出点击指令后无等待, 故需要等候窗口弹出
                            Thread.Sleep(500);
                        }

                        //默认设置成'现货白银1000', 如果打开建仓单需要其它商品, 改这里.
                        if (!getJianCangDanShangPinName().Contains(Constants.XHBY1000))
                        {
                            //当前不是'现货白银1000', 改成'现货白银1000'
                            setJianCangDanShangPin(Constants.XHBY1000);
                        }

                    }
                }
                catch
                {
                    Log.WriteLogFile("openJianCangDanWindow -> 打开建仓单窗口失败");
                }
            }//lock section
        }

        //关闭建仓单(建仓单窗口已经打开)
        private void closeJianCangDanWindow()
        {
            IntPtr hwnd = findJianCangDanWindow();

            if (hwnd != IntPtr.Zero)
            {
                FindWindow fw = new FindWindow(hwnd, null, "取消");

                SendMessage(fw.FoundHandle, Win32.WM_CLICK, 0, 0);     //发送点击按钮的消息
            }
        }

        //打开平仓单(主界面存在, 点击平仓单按钮)
        private void openPingCangDanWindow()
        {
            lock (myOpenJianCangDanOrPingCangDanWindowLock)
            {
                closeJianCangDanWindow();

                IntPtr hwnd = findMainWindow();

                if (findPingCangDanWindow() == IntPtr.Zero && hwnd != IntPtr.Zero)//平仓单窗口未打开且主窗口打开
                {
                    //点击坐标, 打开平仓单窗口
                    FindWindow fw = new FindWindow(hwnd, null, "toolStrip1");

                    PostMessage(fw.FoundHandle, Win32.WM_LBUTTONDOWN, 0, Win32.MakeLong(55, 22));
                    PostMessage(fw.FoundHandle, Win32.WM_LBUTTONUP, 0, Win32.MakeLong(55, 22));
                    //PostMessage 是异步消息, 发出点击指令后无等待, 故需要等候窗口弹出
                    Thread.Sleep(500);
                }
            }//lock section
        }

        //关闭平仓单(平仓单窗口已经打开)
        private void closePingCangDanWindow()
        {
            IntPtr hwnd = findPingCangDanWindow();

            if (hwnd != IntPtr.Zero)
            {
                FindWindow fw = new FindWindow(hwnd, null, "取消");

                SendMessage(fw.FoundHandle, Win32.WM_CLICK, 0, 0);     //发送点击按钮的消息
            }
        }

        //找平仓单窗口句柄
        private IntPtr findPingCangDanWindow()
        {
            IntPtr hwnd = FindWindow(null, "平仓单");

            //if (hwnd != IntPtr.Zero)
            //{
            //    //Log.WriteLogFile("找到窗口: 平仓单");
            //}
            //else
            //{
            //    Log.WriteLogFile("没有找到窗口: 平仓单");
            //}
            return hwnd;
        }

        //读出平仓单中的报价值句柄
        public IntPtr getReportValueHandleFromPingCangDanWindow()
        {
            IntPtr rtHandle = IntPtr.Zero;
            try
            {
                IntPtr pingCangDanHwnd = findPingCangDanWindow();

                if (pingCangDanHwnd != IntPtr.Zero)
                {
                    FindWindow fw = new FindWindow(pingCangDanHwnd, null, "允许成交价和报价最大点差");//找"允许成交价和报价最大点差"控件, 报价控件是它的上一个控件, 由于报价控件没有caption, 故用此方法

                    if (fw.FoundHandle != IntPtr.Zero)
                    {
                        //找它的上一个控件
                        IntPtr reportValueHandle = GetWindow(fw.FoundHandle, 3);

                        if (reportValueHandle != IntPtr.Zero)
                        {
                            rtHandle = reportValueHandle;
                        }
                        else
                        {
                            Log.WriteLogFile("getReportValueHandleFromPingCangDanWindow -> reportValueHandle is zero");
                        }
                    }
                    else
                    {
                        //输出没有找到此控件
                        Log.WriteLogFile("getReportValueHandleFromPingCangDanWindow -> 没有找到 '允许成交价和报价最大点差' 句柄");
                    }
                }
                else
                {
                    //Log.WriteLogFile("getReportValueHandleFromPingCangDanWindow -> 没有找到 '平仓单窗口' 句柄");
                }
            }
            catch
            {
                Log.WriteLogFile("getReportValueHandleFromPingCangDanWindow -> 出错");
            }
            return rtHandle;
        }

        //找建仓单窗口句柄
        private IntPtr findJianCangDanWindow()
        {
            IntPtr hwnd = FindWindow(null, "建仓单");

            //if (hwnd != IntPtr.Zero)
            //{
            //    //Log.WriteLogFile("找到窗口: 建仓单");
            //}
            //else
            //{
            //    Log.WriteLogFile( "没有找到窗口: 建仓单");
            //}
            return hwnd;
        }

        public bool isJianCangDanOpen()
        {
            return this.findJianCangDanWindow() != IntPtr.Zero;
        }


        //读出建仓单中的报价值句柄
        public IntPtr getReportValueHandleFromJianCangDanWindow()
        {
            IntPtr rtHandle = IntPtr.Zero;

            try
            {
                IntPtr jianCangDanHwnd = findJianCangDanWindow();

                if (jianCangDanHwnd != IntPtr.Zero)
                {
                    FindWindow fw = new FindWindow(jianCangDanHwnd, null, "允许成交价和报价的最大点差");//找"允许成交价和报价的最大点差"控件, 报价控件是它的下一个控件, 由于报价控件没有caption, 故用此方法

                    if (fw.FoundHandle != IntPtr.Zero)
                    {
                        //找它的下一个控件
                        IntPtr reportValueHandle = GetWindow(fw.FoundHandle, 2);

                        if (reportValueHandle != IntPtr.Zero)
                        {
                            rtHandle = reportValueHandle;
                        }
                    }
                    else
                    {
                        //输出没有找到此控件
                        Log.WriteLogFile("getReportValueHandleFromJianCangDanWindow -> 没有找到建仓单中的报价值句柄");
                    }

                }
                else
                {
                    //Log.WriteLogFile("getReportValueHandleFromJianCangDanWindow -> 没有找到'建仓单窗口'句柄");
                }
            }
            catch
            {
                Log.WriteLogFile("getReportValueHandleFromJianCangDanWindow -> 读出建仓单中的报价值句柄 出错");
            }
            return rtHandle;
        }

        //读出报价句柄里的值, 在主界面显示
        public string getReportValueFromHandle(IntPtr h)
        {
            string rt = "";//返回值
            try
            {
                if (h != IntPtr.Zero)
                {
                    string w = "";
                    IntPtr ptr = Marshal.StringToHGlobalAnsi(w);

                    SendMessage(h, Win32.WM_GETTEXT, 10, (int)ptr);

                    string reportValue = Marshal.PtrToStringAnsi(ptr);

                    if (reportValue.Length > 0)
                    {
                        try
                        {
                            GlobalValues.UI_AG_SELLVALUE = int.Parse(reportValue);
                            rt = reportValue;
                        }
                        catch
                        {
                            Log.WriteLogFile("string to int error. reportValue = " + reportValue);
                        }
                    }
                }
                else
                {
                    Log.WriteLogFile("getReportValueFromHandle -> 无法读出报价句柄.");
                }
            }
            catch (Exception ex)
            {
                Log.WriteLogFile(ex.ToString());
            }
            return rt;
        }

        //读出建仓单手数值
        private int getJianCangDanShouShu()
        {
            int rc = 0;

            FindWindow fw = new FindWindow(findJianCangDanWindow(), "WindowsForms10.EDIT.app.0.33c0d9d", null);

            string w = "";
            IntPtr ptr = Marshal.StringToHGlobalAnsi(w);

            SendMessage(fw.FoundHandle, Win32.WM_GETTEXT, 10, (int)ptr);

            string shouShu = Marshal.PtrToStringAnsi(ptr);

            try
            {
                rc = int.Parse(shouShu);
            }
            catch
            {
                Log.WriteLogFile("读建仓单手数时出错.");
            }

            return rc;
        }

        //设置建仓单手数值
        private void setJianCangDanShouShu(string value)
        {
            IntPtr hwnd = findJianCangDanWindow();

            if (hwnd != IntPtr.Zero)
            {
                FindWindow fw = new FindWindow(hwnd, "WindowsForms10.EDIT.app.0.33c0d9d", null);

                if (fw.FoundHandle != IntPtr.Zero)
                {
                    SendMessage(fw.FoundHandle, Win32.WM_SETTEXT, 0, value);
                }
            }
        }

        //读出平仓单手数值
        private int getPingCangDanShouShu()
        {
            int rc = 0;

            FindWindow fw = new FindWindow(findPingCangDanWindow(), null, "商品");//手数控件在商品的下一个同级窗口的第二个editbox窗口

            if (fw.FoundHandle != IntPtr.Zero)
            {
                //找它的下一个控件窗口
                IntPtr nextWinHandle = GetWindow(fw.FoundHandle, 2);

                if (nextWinHandle != IntPtr.Zero)
                {
                    FindWindow fw1 = new FindWindow(nextWinHandle, "WindowsForms10.EDIT.app.0.33c0d9d", null);
                    string w = "";
                    IntPtr ptr = Marshal.StringToHGlobalAnsi(w);

                    SendMessage(fw1.FoundHandle, Win32.WM_GETTEXT, 10, (int)ptr);

                    string shouShu = Marshal.PtrToStringAnsi(ptr);

                    try
                    {
                        rc = int.Parse(shouShu);
                    }
                    catch
                    {
                        Log.WriteLogFile("读平仓单手数时出错.");
                    }
                }
            }

            return rc;
        }

        //设置平仓单手数值
        private void setPingCangDanShouShu(string value)
        {
            IntPtr hwnd = findPingCangDanWindow();

            if (hwnd != IntPtr.Zero)
            {
                FindWindow shangPinHwnd = new FindWindow(hwnd, null, "商品");//手数控件在商品的下一个同级窗口的第二个editbox窗口

                if (shangPinHwnd.FoundHandle != IntPtr.Zero)
                {
                    //找它的下一个控件窗口
                    IntPtr nextWinHandle = GetWindow(shangPinHwnd.FoundHandle, 2);

                    if (nextWinHandle != IntPtr.Zero)
                    {
                        FindWindow fw = new FindWindow(nextWinHandle, "WindowsForms10.EDIT.app.0.33c0d9d", null);

                        if (fw.FoundHandle != IntPtr.Zero)
                        {
                            SendMessage(fw.FoundHandle, Win32.WM_SETTEXT, 0, value);
                        }
                    }
                }

            }
        }

        //读出建仓单商品种类
        private string getJianCangDanShangPinName()
        {
            string rc = "";

            IntPtr jianCangDanWindowHandle = findJianCangDanWindow();

            if (jianCangDanWindowHandle != IntPtr.Zero)
            {
                //建仓单商品种类句柄位于'商品'句柄的下一个同级句柄
                FindWindow shangPin = new FindWindow(jianCangDanWindowHandle, null, "商　　品");
                if (shangPin.FoundHandle != IntPtr.Zero)
                {
                    //找它的下一个句柄
                    IntPtr shangPinNameHandle = GetWindow(shangPin.FoundHandle, 2);

                    if (shangPinNameHandle != IntPtr.Zero)
                    {
                        string w = "";
                        IntPtr ptr = Marshal.StringToHGlobalAnsi(w);

                        SendMessage(shangPinNameHandle, Win32.WM_GETTEXT, 50, (int)ptr);//发消息读出内容

                        string shangPinName = Marshal.PtrToStringAnsi(ptr);

                        if (shangPinName != null && shangPinName.Length > 0)
                        {
                            rc = shangPinName;
                        }
                        else
                        {
                            Log.WriteLogFile("取商品名时出错");
                        }
                    }
                    else
                    {
                        Log.WriteLogFile("没有找到建仓单商品COMBOBOX句柄");
                    }
                }
                else
                {
                    Log.WriteLogFile("没有找到建仓单'商   品'句柄");
                }
            }
            else
            {
                //无法读出建仓单商品种类
                Log.WriteLogFile("getJianCangDanShangPinName -> 没有找到建仓单句柄");
            }
            Console.WriteLine("商品为: " + rc);
            return rc;
        }

        //设置建仓单商品种类
        private void setJianCangDanShangPin(string name)
        {
            IntPtr jianCangDanWindowHandle = findJianCangDanWindow();

            if (jianCangDanWindowHandle != IntPtr.Zero)
            {
                //建仓单商品种类句柄位于'商    品'句柄的下一个同级句柄
                FindWindow shangPin = new FindWindow(jianCangDanWindowHandle, null, "商　　品");
                if (shangPin.FoundHandle != IntPtr.Zero)
                {
                    //找它的下一个句柄
                    IntPtr shangPinNameHandle = GetWindow(shangPin.FoundHandle, 2);

                    if (shangPinNameHandle != IntPtr.Zero)
                    {
                        SendMessage(shangPinNameHandle, Win32.CB_SHOWDROPDOWN, 1, 0);//打开列表

                        Thread.Sleep(100);//等待列表打开

                        SendMessage(shangPinNameHandle, Win32.CB_SELECTSTRING, 0, name);//选择

                        SendMessage(shangPinNameHandle, Win32.WM_KEYDOWN, Win32.VK_RETURN, 0);  //响应回车键 

                        SendMessage(shangPinNameHandle, Win32.CB_SHOWDROPDOWN, 0, 0);//关闭列表

                        Thread.Sleep(100);
                    }
                    else
                    {
                        Log.WriteLogFile("没有找到建仓单商品COMBOBOX句柄");
                    }
                }
                else
                {
                    Log.WriteLogFile("没有找到建仓单'商   品'句柄");
                }
            }
            else
            {
                Log.WriteLogFile("getJianCangDanShangPinName -> 没有找到建仓单句柄");
            }
        }

        //读出平仓单商品种类
        private string getPingCangDanShangPinName()
        {
            string rc = "";

            IntPtr pingCangDanWindowHandle = findPingCangDanWindow();

            if (pingCangDanWindowHandle != IntPtr.Zero)
            {
                //平仓单商品种类句柄位于'最大'句柄的下一个同级句柄
                FindWindow zuiDa = new FindWindow(pingCangDanWindowHandle, null, "最大");
                if (zuiDa.FoundHandle != IntPtr.Zero)
                {
                    //找它的下一个句柄
                    IntPtr shangPinNameHandle = GetWindow(zuiDa.FoundHandle, 2);

                    if (shangPinNameHandle != IntPtr.Zero)
                    {
                        string w = "";
                        IntPtr ptr = Marshal.StringToHGlobalAnsi(w);

                        SendMessage(shangPinNameHandle, Win32.WM_GETTEXT, 50, (int)ptr);

                        string shangPinName = Marshal.PtrToStringAnsi(ptr);

                        if (shangPinName != null && shangPinName.Length > 0)
                        {
                            rc = shangPinName;
                        }
                        else
                        {
                            Log.WriteLogFile("取商品名时出错");
                        }
                    }
                    else
                    {
                        Log.WriteLogFile("没有找到平仓单商品COMBOBOX句柄");
                    }
                }
                else
                {
                    Log.WriteLogFile("没有找到平仓单'最大'句柄");
                }
            }
            else
            {
                //无法读出平仓单商品种类
                Log.WriteLogFile("getPingCangDanShangPinName -> 没有找到平仓单句柄");
            }

            return rc;
        }

        //设置平仓单商品种类
        private void setPingCangDanShangPin(string name)
        {
            IntPtr pingCangDanWindowHandle = findPingCangDanWindow();

            if (pingCangDanWindowHandle != IntPtr.Zero)
            {
                //平仓单商品种类句柄位于'最大'句柄的下一个同级句柄
                FindWindow zuiDa = new FindWindow(pingCangDanWindowHandle, null, "最大");
                if (zuiDa.FoundHandle != IntPtr.Zero)
                {
                    //找它的下一个句柄
                    IntPtr shangPinNameHandle = GetWindow(zuiDa.FoundHandle, 2);

                    if (shangPinNameHandle != IntPtr.Zero)
                    {
                        SendMessage(shangPinNameHandle, Win32.CB_SHOWDROPDOWN, 1, 0);//打开列表

                        Thread.Sleep(200);//等待列表打开

                        SendMessage(shangPinNameHandle, Win32.CB_SELECTSTRING, 0, name);//选择

                        SendMessage(shangPinNameHandle, Win32.WM_KEYDOWN, Win32.VK_RETURN, 0);  //响应回车键 

                        SendMessage(shangPinNameHandle, Win32.CB_SHOWDROPDOWN, 0, 0);//关闭列表
                    }
                    else
                    {
                        Log.WriteLogFile("没有找到平仓单商品COMBOBOX句柄");
                    }
                }
                else
                {
                    Log.WriteLogFile("没有找到平仓单'最大'句柄");
                }
            }
            else
            {
                //无法读出平仓单商品种类
                Log.WriteLogFile("getPingCangDanShangPinName -> 没有找到平仓单句柄");
            }
        }

        public void getAndSetAg1000Quantity()
        {
            //目前无法从HTTPS返回包中分手出持单量, 所以只能通过平仓界面来获取目前持仓量
            if (findMainWindow() != IntPtr.Zero)
            {
                //打开平仓单窗口
                openPingCangDanWindow();

                Thread.Sleep(500);//必须停一下, 等待窗口出现

                //设置商品
                if (!getPingCangDanShangPinName().Contains(Constants.XHBY1000))
                {
                    setPingCangDanShangPin(Constants.XHBY1000);
                }
                //打开后, 默认是选中'买入', 读出当前空单量
                GlobalValues.AG1000_K = getPingCangDanShouShu();
                Console.WriteLine("当前空单量 : " + GlobalValues.AG1000_K);

                //点击'卖出', 读出当前多单量
                FindWindow fw = new FindWindow(findPingCangDanWindow(), null, "卖出");
                if (fw.FoundHandle != IntPtr.Zero)
                {
                    SendMessage(fw.FoundHandle, Win32.WM_CLICK, 0, 0);

                    GlobalValues.AG1000_D = getPingCangDanShouShu();

                    Console.WriteLine("当前多单量 : " + GlobalValues.AG1000_D);
                }

                closePingCangDanWindow();
            }
        }

        public void test()
        {
            //Console.WriteLine("WindowOperation -> test() in");
            //IntPtr mainWindowHwnd = findMainWindow();

            //if (mainWindowHwnd != IntPtr.Zero)
            //{
            //    FindWindow fw = new FindWindow(mainWindowHwnd, null, "toolStrip1");

            //    if (fw.FoundHandle == IntPtr.Zero)
            //    { 
            //        //有主界面, 但没登录
            //        //点击'交易系统', 开打登录窗口
            //        FindWindow fw1 = new FindWindow(mainWindowHwnd, "WindowsForms10.SysTreeView32.app.0.33c0d9d", null);
            //        if (fw1.FoundHandle != IntPtr.Zero)
            //        {
            //            Console.WriteLine("fw1.FoundHandle = " + fw1.FoundHandle);
            //            short pointX;
            //            short pointY;
            //            pointX = pointY = 45;
            //            PostMessage(fw1.FoundHandle, Win32.WM_LBUTTONDOWN, 0, Win32.MakeLong(pointX, pointY));
            //            PostMessage(fw1.FoundHandle, Win32.WM_LBUTTONUP, 0, Win32.MakeLong(pointX, pointY));
            //            //PostMessage 是异步消息, 发出点击指令后无等待, 故需要等候窗口弹出
            //            Thread.Sleep(500);
            //        }
            //    }
            //}
            
        }
    }
}
